package com.jumi.microservice.service.logistics.admin;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.base.dto.ExportExcelCommonResponse;
import com.jumi.microservice.common.exception.BaseException;
import com.jumi.microservice.common.page.TableDataInfo;
import com.jumi.microservice.dto.excel.UserOrderGoodsInfo;
import com.jumi.microservice.dto.logistics.admin.SelfWaitSendGoodsResponse;
import com.jumi.microservice.dto.logistics.admin.SelfWaitSendRequest;
import com.jumi.microservice.dto.logistics.admin.SelfWaitSendResponse;
import com.jumi.microservice.dto.logistics.excel.BatchUpdateRealLogisticsNo;
import com.jumi.microservice.dto.logistics.excel.SelfWaitSend;
import com.jumi.microservice.entity.*;
import com.jumi.microservice.enumerate.*;
import com.jumi.microservice.mapper.*;
import com.jumi.microservice.material.dto.warehouse.JmWarehouseResponse;
import com.jumi.microservice.material.service.IJmWarehouseService;
import com.jumi.microservice.service.logistics.excel.BatchUpdateRealLogisticsNoListener;
import com.jumi.microservice.service.logistics.excel.SelfWaitSendListener;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author by mazhao
 * @Classname SelfWaitSendService
 * @Description TODO
 * @Date 2020/8/25 15:12
 */
@Service
@RefreshScope
public class SelfWaitSendService {

    private static final Logger log = LoggerFactory.getLogger(SelfWaitSendService.class);

    @Resource
    LogisticsGoodsMapper logisticsGoodsMapper;

    @Resource
    OrderLogisticsMapper orderLogisticsMapper;

    @Resource
    SendService sendService;

    @DubboReference
    IJmWarehouseService iWarehouseService;

    @Resource
    UserOrderMapper userOrderMapper;
    @Resource
    OrderGoodsMapper orderGoodsMapper;
    @Resource
    OrderLogMapper orderLogMapper;
    @Resource
    AsyncSendService asyncSendService;

    /**
     * 自营待发货列表
     *
     * @param request
     * @return
     */
    public TableDataInfo<SelfWaitSendResponse> selfWaitSendList(SelfWaitSendRequest request) {
        TableDataInfo<SelfWaitSendResponse> tableDataInfo = new TableDataInfo<>();
        List<SelfWaitSendResponse> result = new ArrayList<>();
        QueryWrapper<LogisticsGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", 0).eq("self_flag", SelfFlagEnum.YES_SELF.getCode())
                .eq("logistics_status", LogisticsStatusEnum.WAIT_SEND.getCode());
        List<LogisticsGoods> logisticsGoodsList = logisticsGoodsMapper.selectList(queryWrapper);
        if (logisticsGoodsList.isEmpty()) {
            tableDataInfo.setRows(result);
            tableDataInfo.setTotal(0L);
            return tableDataInfo;
        }
        List<Integer> orderIds = logisticsGoodsList.stream().map(LogisticsGoods::getOrderId).collect(Collectors.toList());
        QueryWrapper<OrderGoods> orderGoodsQueryWrapper = new QueryWrapper<>();
        orderGoodsQueryWrapper.in("order_id", orderIds);
        List<OrderGoods> orderGoods = orderGoodsMapper.selectList(orderGoodsQueryWrapper);
        Map<String, List<SelfWaitSendGoodsResponse>> map = new HashMap<>();
        for (LogisticsGoods logisticsGoods : logisticsGoodsList) {
            Set<Byte> set = orderGoods.stream().filter(g -> g.getOrderId().equals(logisticsGoods.getOrderId()))
                    .map(OrderGoods::getGoodsStatus).collect(Collectors.toSet());
            if (set.contains(LogisticsStatusEnum.WAIT_RECEIVE.getCode()) || set.contains(LogisticsStatusEnum.PART_SEND.getCode())) {
                continue;
            }
            if(set.size()==1 && set.contains(LogisticsStatusEnum.CANCEL.getCode())){
                continue;
            }
            SelfWaitSendGoodsResponse selfWaitSendGoodsResponse = new SelfWaitSendGoodsResponse();
            BeanUtils.copyProperties(logisticsGoods, selfWaitSendGoodsResponse);
            if (map.containsKey(logisticsGoods.getLogisticsNo())) {
                map.get(logisticsGoods.getLogisticsNo()).add(selfWaitSendGoodsResponse);
            } else {
                List<SelfWaitSendGoodsResponse> list = new ArrayList<>();
                list.add(selfWaitSendGoodsResponse);
                map.put(logisticsGoods.getLogisticsNo(), list);
            }
        }
        List<String> logisticsNos = new ArrayList<>(map.keySet());
        QueryWrapper<OrderLogistics> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("del_flag", 0).in("logistics_no", logisticsNos).orderByDesc("create_time");
        if (request.getWarehouse() != null) {
            queryWrapper1.eq("warehouse", request.getWarehouse());
        }
        if (request.getBenchmarkTime() != null) {
            queryWrapper1.le("create_time", request.getBenchmarkTime());
        }
        IPage<OrderLogistics> page = new Page(request.getPageNum(), request.getPageSize());
        IPage<OrderLogistics> iPage = orderLogisticsMapper.selectPage(page, queryWrapper1);
        List<OrderLogistics> orderLogisticsList = iPage.getRecords();
        for (OrderLogistics orderLogistics : orderLogisticsList) {
            SelfWaitSendResponse selfWaitSendResponse = new SelfWaitSendResponse();
            BeanUtils.copyProperties(orderLogistics, selfWaitSendResponse);
            selfWaitSendResponse.setList(map.get(orderLogistics.getLogisticsNo()));
            selfWaitSendResponse.setLogisticsType(getLogisticsType(map.get(orderLogistics.getLogisticsNo()), orderLogistics.getSpiltMergeStatus()));
            result.add(selfWaitSendResponse);
        }
        tableDataInfo.setRows(result);
        tableDataInfo.setTotal(iPage.getTotal());
        return tableDataInfo;
    }

    /**
     * 获取包裹类型
     *
     * @param paramList
     * @param logisticsType
     * @return
     */
    public Byte getLogisticsType(List<SelfWaitSendGoodsResponse> paramList, Byte logisticsType) {
        if (logisticsType.equals(SpiltMergeStatusEnum.NO_SPILT_MERGE.getCode())) {
            return SpiltMergeStatusEnum.NO_SPILT_MERGE.getCode();
        } else {
            List<String> list = paramList.stream().map(SelfWaitSendGoodsResponse::getOrderNo).collect(Collectors.toList());
            Set<String> set = new HashSet<>(list);
            if (set.size() > 1) {
                return SpiltMergeStatusEnum.MERGE.getCode();
            }
        }
        return SpiltMergeStatusEnum.SPILT.getCode();
    }


    /**
     * 导出
     */
    public ExportExcelCommonResponse<SelfWaitSend> excelExport(SelfWaitSendRequest request,Long uid,String name) {
        ExportExcelCommonResponse<SelfWaitSend> response = new ExportExcelCommonResponse<>();
        List<SelfWaitSend> result = new ArrayList<>();
        Map<Integer, String> warehouseMap = getWarehouseMap();
        List<String> logisticsNos = null;
        if(request.getLogisticsNos()!=null && !request.getLogisticsNos().trim().isEmpty()){
            logisticsNos = Arrays.asList(request.getLogisticsNos().split(","));
        }
        List<UserOrderGoodsInfo> list = userOrderMapper.getSelfOrders(logisticsNos,request.getBenchmarkTime(),request.getWarehouse());
        List<Integer> orderIds = new ArrayList<>();
        List<JSONObject> addLogList = new ArrayList<>();
        for (UserOrderGoodsInfo logisticsGoods : list) {
            SelfWaitSend excelExport = new SelfWaitSend();
            excelExport.setLogisticsNo(logisticsGoods.getLogisticsNo());
            excelExport.setReceiverName(logisticsGoods.getReceiverName());
            excelExport.setReceiverPhone(logisticsGoods.getReceiverPhone());
            excelExport.setReceiverAddress(logisticsGoods.getReceiverAddress());
            excelExport.setGoodsId(logisticsGoods.getGoodsId());
            excelExport.setGoodsName(logisticsGoods.getGoodsName());
            excelExport.setGoodsPrice(logisticsGoods.getGoodsPrice());
            excelExport.setGoodsAmount(logisticsGoods.getGoodsAmount());
            excelExport.setRealSendAmount(logisticsGoods.getGoodsAmount());
            excelExport.setOrderCreateTime(logisticsGoods.getOrderCreateTime());
            excelExport.setPayTime(logisticsGoods.getPayTime());
            excelExport.setOrderRemark(logisticsGoods.getOrderRemark());
            excelExport.setRemark("");
            BigDecimal totalWeight = logisticsGoods.getGoodsWeight().multiply(new BigDecimal(logisticsGoods.getGoodsAmount()));
            excelExport.setTotalWeight(totalWeight + "kg");
            if (warehouseMap.containsKey(logisticsGoods.getRealWarehouse())) {
                excelExport.setWarehouse(warehouseMap.get(logisticsGoods.getRealWarehouse()));
            }
            excelExport.setOrderNo(logisticsGoods.getOrderNo());
            excelExport.setOrderId(logisticsGoods.getOrderId());
            excelExport.setBuyId(logisticsGoods.getBuyerId());
            excelExport.setWarehouseId(logisticsGoods.getRealWarehouse());
            orderIds.add(logisticsGoods.getOrderId());
            result.add(excelExport);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("uid",uid);
            jsonObject.put("name",name);
            jsonObject.put("orderNo",logisticsGoods.getOrderNo());
            if(request.getIsUpdateOrderStatus().equals((byte) 1)){
                jsonObject.put("log","自营未对接导出excel 订单号："+logisticsGoods.getOrderNo()+"，商品名称："+logisticsGoods.getGoodsName()+"，数量："+logisticsGoods.getGoodsAmount());
            }else{
                jsonObject.put("log","自营导出excel 订单号："+logisticsGoods.getOrderNo()+"，商品名称："+logisticsGoods.getGoodsName()+"，数量："+logisticsGoods.getGoodsAmount());
            }
            addLogList.add(jsonObject);
        }
        if(request.getIsUpdateOrderStatus().equals((byte)1)){
            asyncSendService.batchUpdateOrderStatus(orderIds);
        }
        asyncSendService.batchAddLog(addLogList,new ArrayList<>());
        response.setData(result);
        response.setFileName("SelfWaitSend.xlsx");
        return response;
    }

//    /**
//     * 插入日志记录表
//     *
//     * @param uid
//     * @param name
//     * @param orderNo
//     * @param log
//     */
//    @Async
//    public boolean addLog(Long uid, String name, String orderNo, String log) {
//        OrderLog orderLog = new OrderLog();
//        orderLog.setOperatorId(uid);
//        orderLog.setOperatorName(name);
//        orderLog.setOrderSn(orderNo);
//        orderLog.setLog(log);
//        orderLog.setUserFlag((byte) 2);
//        int rows = orderLogMapper.insert(orderLog);
//        return rows > 0;
//    }

    /**
     * 自营待发货导入
     */
    public List<String> excelImport(HttpServletRequest request, Long uid, String name) throws IOException {
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
        try {
            EasyExcel.read(request.getInputStream(), SelfWaitSend.class, new SelfWaitSendListener(sendService, uid, name)).sheet().doRead();
        } catch (ExcelAnalysisException | ExcelCommonException e) {
            throw new BaseException(500, "文件异常，请检查确认");
        }
        return SendService.selfWaitSendError;
    }

    /**
     * 获取全部仓库信息
     *
     * @return
     */
    public Map<Integer, String> getWarehouseMap() {
        List<JmWarehouseResponse> list = iWarehouseService.findAll().getData();
        Map<Integer, String> map = new HashMap<>(list.size());
        for (JmWarehouseResponse jmWarehouseResponse : list) {
            map.put(jmWarehouseResponse.getWarehouseId().intValue(), jmWarehouseResponse.getWarehouseName());
        }
        return map;
    }

    /**
     * 批量修改物流单号导入
     */
    public List<String> batchUpdateRealLogisticsNo(HttpServletRequest request, Long uid, String name) throws IOException {
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
        try {
            EasyExcel.read(request.getInputStream(), BatchUpdateRealLogisticsNo.class, new BatchUpdateRealLogisticsNoListener(sendService, uid, name)).sheet().doRead();
        } catch (ExcelAnalysisException | ExcelCommonException e) {
            throw new BaseException(500, "文件异常，请检查确认");
        }
        return SendService.updateLogisticsNoError;
    }

}
